Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports System.Runtime.InteropServices

Namespace DirectX

    Module mDirectX

        Public Sub Init()


            Dim Caps As Direct3D.Caps
            Caps = Direct3D.Manager.GetDeviceCaps(0, Direct3D.DeviceType.Hardware)
            If Caps.PixelShaderVersion.Major >= 2 Then
                'DirectX.bUsePixelShaders = True
            End If

            If DirectX.DispMode.Width = 0 Then
                'DirectX.DispMode.Width = Constants.gLoginResX
                'DirectX.DispMode.Height = Constants.gLoginResY
                DirectX.DispMode.Width = Constants.gGameResX
                DirectX.DispMode.Height = Constants.gGameResY

            End If
            If DirectX.Windowed Then Globals.fGameForm.ClientSize = New Size(DirectX.DispMode.Width, DirectX.DispMode.Height)
            DirectX.DispMode.Format = DirectX.ColorFormat

            DirectX.PresentParam = New PresentParameters()

            SetupPresentParams(DirectX.PresentParam)

            DirectX.D3D = New Direct3D.Device(Manager.Adapters.Default.Adapter, Direct3D.DeviceType.Hardware, Globals.fGameForm, CreateFlags.HardwareVertexProcessing Or CreateFlags.PureDevice, DirectX.PresentParam)
            'DirectX.D3D = New Direct3D.Device(Manager.Adapters.Default.Adapter, Direct3D.DeviceType.Hardware, Globals.fGameForm, CreateFlags.SoftwareVertexProcessing, DirectX.PresentParam)


            'If bUsePixelShaders Then

            '    Dim gs As GraphicsStream = ShaderLoader.FromFile(Globals.sRootPath & "\grayscale.ps", Nothing, Nothing)
            '    GrayScalePixelShader = New PixelShader(D3D, gs)
            '    gs.Dispose()

            '    gs = ShaderLoader.FromFile(Globals.sRootPath & "\normal.ps", Nothing, Nothing)
            '    NormalPixelShader = New PixelShader(D3D, gs)
            '    gs.Dispose()

            '    gs = ShaderLoader.FromFile(Globals.sRootPath & "\magic.ps", Nothing, Nothing)
            '    MagicPixelShader = New PixelShader(D3D, gs)
            '    gs.Dispose()

            '    gs = ShaderLoader.FromFile(Globals.sRootPath & "\shadow.ps", Nothing, Nothing)
            '    ShadowPixelShader = New PixelShader(D3D, gs)
            '    gs.Dispose()
            'End If

            LoadRes()
            CalcScreenRect()

        End Sub

        Private Sub SetupPresentParams(ByRef pp As PresentParameters)

            pp.BackBufferCount = 1
            pp.BackBufferFormat = DirectX.ColorFormat
            pp.BackBufferWidth = DirectX.DispMode.Width
            pp.BackBufferHeight = DirectX.DispMode.Height

            pp.SwapEffect = SwapEffect.Discard
            pp.PresentationInterval = PresentInterval.Immediate

            pp.ForceNoMultiThreadedFlag = False

            pp.PresentFlag = PresentFlag.None

            pp.Windowed = DirectX.Windowed
            pp.MultiSample = MultiSampleType.None
            pp.MultiSampleQuality = 0

            pp.EnableAutoDepthStencil = True
            pp.AutoDepthStencilFormat = DepthFormat.D16

            pp.DeviceWindow = Globals.fGameForm

        End Sub

        Public Sub LoadRes()

            D3D.Transform.View = MainMatrix

            SetRenderStates()

            GameSprite = New Direct3D.Sprite(D3D)
            GameLine = New Line(D3D)

            GameSurface = DirectX.D3D.GetBackBuffer(0, 0, BackBufferType.Mono)

            PlayerTexture = New Direct3D.Texture(DirectX.D3D, DispMode.Width, DispMode.Height, 1, Usage.RenderTarget, DirectX.ColorFormat, Pool.Default)
            PlayerSurface = PlayerTexture.GetSurfaceLevel(0)

            Dim w As Integer, h As Integer

            w = Constants.gGameResX * GameWindow.DrawAreaFactorX
            h = Constants.gGameResY * GameWindow.DrawAreaFactorY

            SkillTexture = New Direct3D.Texture(DirectX.D3D, 304, 336, 1, Usage.RenderTarget, DirectX.ColorFormat, Pool.Default)
            SkillSurface = SkillTexture.GetSurfaceLevel(0)

            FloorItemsTexture = New Direct3D.Texture(DirectX.D3D, DispMode.Width, DispMode.Height, 1, Usage.RenderTarget, DirectX.ColorFormat, Pool.Default)
            FloorItemsSurface = FloorItemsTexture.GetSurfaceLevel(0)

            LightTexture = New Direct3D.Texture(DirectX.D3D, DispMode.Width, DispMode.Height, 1, Usage.RenderTarget,DirectX.ColorFormat, Pool.Default)
            LightSurface = LightTexture.GetSurfaceLevel(0)

            InventoryTexture = New Direct3D.Texture(DirectX.D3D, Inventory.cCellSize * 6, Inventory.cCellSize * 8, 1, Usage.RenderTarget, DirectX.ColorFormat, Pool.Default)
            InventorySurface = InventoryTexture.GetSurfaceLevel(0)

            'TextTexture = New Direct3D.Texture(DirectX.D3D, DispMode.Width, DispMode.Height, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default)
            'TextSurface = TextTexture.GetSurfaceLevel(0)

            'Line = New Direct3D.Line(D3D)

            ProFont9 = New Fonts.MirFont(D3D, Constants.FontName, Globals.fontSize)
            'DirectX.SmallFont = New Direct3D.Font(DirectX.D3D, DirectX.SmallFont_M)
            'DirectX.LargeFont = New Direct3D.Font(DirectX.D3D, DirectX.LargeFont_M)
            'DirectX.ToolTipFont = New Direct3D.Font(DirectX.D3D, DirectX.ToolTipFont_M)

            'CursorTexture = TextureLoader.FromFile(D3D, Globals.sDataPath & "cursor.bmp", 0, 0, 0, 0, _
            'Format.A8R8G8B8, Pool.Managed, Filter.None, Filter.None, _
            'Color.FromArgb(255, 0, 0, 0).ToArgb())

            Windows.ReloadGUISurfaces()

            Libs.Shutdown()
            Libs.Init()

        End Sub

        Private Sub SetRenderStates()

            D3D.RenderState.Lighting = False
            D3D.RenderState.AlphaBlendEnable = True
            D3D.RenderState.SourceBlend = Blend.SourceAlpha
            D3D.RenderState.DestinationBlend = Blend.InvSourceAlpha
            D3D.RenderState.AlphaTestEnable = True
            D3D.RenderState.ReferenceAlpha = 0
            D3D.RenderState.AlphaFunction = Compare.Greater
            D3D.RenderState.ZBufferEnable = True
            D3D.RenderState.ZBufferWriteEnable = True
            D3D.RenderState.ZBufferFunction = Compare.LessEqual

        End Sub

        Public Sub DeviceRecovery()

            'when we lose the device, this code will run

            Try
                DirectX.D3D.TestCooperativeLevel()
            Catch e As DeviceLostException
                'do nothing
            Catch e As DeviceNotResetException

                Try

                    SetupPresentParams(DirectX.PresentParam)
                    DirectX.D3D.Reset(DirectX.PresentParam)
                    LoadRes()

                    DirectX.DeviceLost = False

                Catch bug As DeviceLostException
                    DirectX.DeviceLost = True
                End Try

            Catch ex As Exception
                DirectX.DeviceLost = True
            End Try

        End Sub

        Public Sub SetResoloution(ByRef w As Integer, ByRef h As Integer)

            DirectX.GameSprite.Dispose()
            DirectX.GameSurface.Dispose()
            DirectX.InventorySurface.Dispose()
            DirectX.PlayerSurface.Dispose()
            DirectX.ProFont9.Dispose()

            DirectX.DispMode.Width = w
            DirectX.DispMode.Height = h
            DirectX.DispMode.Format = Manager.Adapters.Default.CurrentDisplayMode.Format

            If Windowed Then
                Globals.fGameForm.ClientSize = New Size(DirectX.DispMode.Width, DirectX.DispMode.Height)
            End If

            DirectX.PresentParam = New PresentParameters()

            SetupPresentParams(DirectX.PresentParam)

            DirectX.D3D.Reset(DirectX.PresentParam)

            LoadRes()
            CalcScreenRect()

        End Sub

        Private Sub CalcScreenRect()

            ScreenRect = New Rectangle(0, 0, DispMode.Width, DispMode.Height)

        End Sub

        Public Function FixedFontHeight(ByRef text As String, ByRef width As Integer, ByRef charwidth As Integer, ByRef charheight As Integer) As Integer

            Dim length As Integer = text.Length
            Dim charsperrow As Integer = Math.DivRem(width, charwidth, Nothing)
            Dim r As Integer
            Dim rows As Integer = Math.DivRem(length, charsperrow, r)
            If r > 0 Then rows += 1

            Return rows * charheight

        End Function

        Public Sub BlitD3D(ByRef tex As Texture, ByRef x As Single, ByRef y As Single, ByRef w As Single, ByRef h As Single, Optional ByRef z As Single = 0.0)

            If tex Is Nothing Then Exit Sub
            If tex.Disposed Then Exit Sub


            'Static sd As SurfaceDescription
            'sd = tex.GetLevelDescription(0)
            'Dim rdest As New Rectangle(x, y, sd.Width, sd.Height)

            'If Not rdest.IntersectsWith(ScreenRect) Then Exit Sub

            'DirectX.GameSprite.Draw(tex, New Rectangle(0.0F, 0.0F, w, h), New Vector3(0.0F, 0.0F, 0.0F), New Vector3(x, y, z), Color.White)

            'Exit Sub

            'Static vertices(3) As CUSTVERT

            'If vertices(0).rhw = 0.0 Then
            'vertices(0).rhw = 1.0
            'vertices(0).tu = 0.0
            'vertices(0).tv = 0.0

            'vertices(1).rhw = 1.0
            'vertices(1).tu = 1.0
            'vertices(1).tv = 0.0

            'vertices(2).rhw = 1.0
            'vertices(2).tu = 0.0
            'vertices(2).tv = 1.0

            'vertices(3).rhw = 1.0
            'vertices(3).tu = 1.0
            'vertices(3).tv = 1.0
            'End If

            'vertices = vertBuff.Lock(0, 0)

            'vertices(0).X = x - 0.5
            'vertices(0).Y = y - 0.5
            'vertices(0).Z = z

            'vertices(1).X = x + sd.Width - 0.5
            'vertices(1).Y = y - 0.5
            'vertices(1).Z = z

            'vertices(2).X = x - 0.5
            'vertices(2).Y = y + sd.Height - 0.5
            'vertices(2).Z = z

            'vertices(3).X = x + sd.Width - 0.5
            'vertices(3).Y = y + sd.Height - 0.5
            'vertices(3).Z = z

            'vertBuff.Unlock()

            'vertBuff.SetData(vertices, 0, LockFlags.None)
            'D3D.SetStreamSource(0, vertBuff, 0)

            'D3D.RenderState.FillMode = FillMode.Solid
            'D3D.SetTexture(0, tex)
            ' Define which vertex buffer should be used

            'D3D.DrawUserPrimitives(PrimitiveType.TriangleStrip, 2, vertices)
            'D3D.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2)

            If w = 0 Or h = 0 Then Exit Sub

            Try

                GameSprite.Draw(tex, New Rectangle(0, 0, w, h), New Vector3(0, 0, 0), New Vector3(x, y, z), Color.White)

            Catch ex As Microsoft.DirectX.Direct3D.DeviceLostException

            Catch ex As Microsoft.DirectX.Direct3D.DeviceNotResetException

            End Try

        End Sub

        Public Sub Shutdown()

            'DirectX.DispMode = Nothing
            DirectX.PresentParam = Nothing

            DirectX.GameSprite.Dispose()

            If bUsePixelShaders Then
                GrayScalePixelShader.Dispose()
                NormalPixelShader.Dispose()
                MagicPixelShader.Dispose()
                ShadowPixelShader.Dispose()
            End If

            DirectX.D3D.EvictManagedResources()

            DirectX.D3D.Dispose()
            DirectX.D3D = Nothing


        End Sub

        Public Sub ToggleFullscreen()

            DirectX.Windowed = Not DirectX.Windowed

            If DirectX.Windowed = True Then
                Shutdown()
                Globals.fGameForm.FormBorderStyle = FormBorderStyle.FixedSingle
                Init()
            Else
                SetResoloution(Constants.gGameResX, Constants.gGameResY)
            End If

        End Sub


    End Module

End Namespace